#include "request.h"
#include <string.h>
#include <stdio.h>

CReqItem::CReqItem(char* name,char* val)
{
    m_pName=0;
    m_pVal=0;
    m_pNext=0;
    int n;
    if(name)
    {
	n=strlen(name)+1;
	if(n)
	{
	    m_pName=new char[n];
	    if(m_pName)
		strncpy(m_pName,name,n);
	}
    }
    if(val)
    {
	n=strlen(val)+1;
	if(n)
	{
	    m_pVal=new char[n];
	    if(m_pVal)
		strncpy(m_pVal,val,n);
	}
    }
}
CReqItem::~CReqItem(void)
{
    if(m_pName) delete[] m_pName;
    if(m_pVal) delete[] m_pVal;
}
char* CReqItem::GetName(void)
{
    if(m_pName) return m_pName;
    return "";
}
char* CReqItem::GetVal(void)
{
    if(m_pVal) return m_pVal;
    return "";
}



    
CRequest::CRequest(void)
{
    m_pBegin=m_pEnd=0;
    m_pSection=0;
    m_nGlobalState=STAT_FINDSECTION;
    m_nState=STAT_UNKNOWN;
    Reset();
}
CRequest::~CRequest(void)
{
    Clear();
}
void CRequest::Clear(void)
{
    while(m_pBegin)
    {
	CReqItem* tmp=m_pBegin;
	m_pBegin=m_pBegin->m_pNext;
	delete tmp;
    }
    m_pBegin=m_pEnd=0;
}
CReqItem* CRequest::Add(char* name,char* val)
{
    CReqItem* tmp=new CReqItem(name,val);
    if(!tmp) return 0;
    if(!m_pBegin)
	m_pBegin=m_pEnd=tmp;
    else
    {
	m_pEnd->m_pNext=tmp;
	m_pEnd=tmp;
    }
    return tmp;
}
const char* CRequest::GetValue(const char*,const char* item,const char* def,int* len)
{
    CReqItem* tmp=m_pBegin;
    const char* val="";
    while(tmp)
    {
	if(!strcmp(tmp->GetName(),item))
	{
	    val=tmp->GetVal();
	    if(def && *def && !*val) val=def;
	    if(len) *len=strlen(val);
	    return val;
	}
	tmp=tmp->m_pNext;
    }
    if(def && *def) val=def;
    if(len) *len=strlen(val);
    return val;
}
bool CRequest::LoadVariables(const char* buf,const char* section)
{
    if(!buf || !*buf || !section) return false;
    m_pSection=(char*)section;
    m_nGlobalState=STAT_APPEND;
    m_nState=STAT_UNKNOWN;
    Reset();
    while(OnChar(*buf))
	buf++;
    return true;
}
void CRequest::AddName(unsigned char ch)
{
    if(m_nName>=TMP_BUF_SIZE) return;
    m_pName[m_nName]=ch;
    m_nName++;
}
void CRequest::AddVal(unsigned char ch)
{
    if(m_nVal>=TMP_BUF_SIZE) return;
    if(ch==' ' && !m_nVal) return;
    m_pVal[m_nVal]=ch;
    m_nVal++;
}
void CRequest::Reset(void)
{
    *m_pName=0;
    *m_pVal=0;
    m_nName=0;
    m_nVal=0;
}
char* CRequest::GetName(void)
{
    m_pName[m_nName]=0;
    return m_pName;
}
char* CRequest::GetVal(void)
{
    m_pVal[m_nVal]=0;
    return m_pVal;
}
		    
bool CRequest::OnChar(unsigned char ch)
{
    if(m_nGlobalState==STAT_STOP) return false;
    if(ch==0x0d) return true;
    if(ch=='\t') ch=' ';
    if(!ch)
    {
	OnValue(GetName(),GetVal());
	Reset();
	return false;
    }
    switch(m_nState)
    {
    case STAT_UNKNOWN:
	if(ch=='[') m_nState=STAT_SECTION;
	else if(ch==';') m_nState=STAT_REM;
	else if(ch!=' ' && ch!=0x0a) {m_nState=STAT_NAME;AddName(ch);}
	break;
    case STAT_REM:
	if(ch==0x0a) m_nState=STAT_UNKNOWN;
	break;
    case STAT_SECTION:
	if(ch==']') {m_nState=STAT_UNKNOWN;OnSection(GetName());Reset();}
	else if(ch!=0x0a && ch!=' ') AddName(ch);
	break;
    case STAT_NAME:
	if(ch=='=') m_nState=STAT_VALUE;
	else if(ch!=0x0a && ch!=' ') AddName(ch);
	break;
    case STAT_VALUE:
	if(ch==0x0a) {m_nState=STAT_UNKNOWN;OnValue(GetName(),GetVal());Reset();}
	else if(ch!=0x0a/* && ch!=' '*/) AddVal(ch);
	break;
    }
    return true;
}
void CRequest::OnValue(char* name,char* val)
{
    if(!name || !val || !*name || !*val) return;
    if(m_nGlobalState==STAT_APPEND)
    {
//	printf("%s=%s\n",name,val);
	Add(name,val);
    }
}
void CRequest::OnSection(char* section)
{
    if(m_nGlobalState==STAT_APPEND)
    {
	m_nGlobalState=STAT_STOP;
    }else if(m_nGlobalState==STAT_FINDSECTION)
    {
	if(!strcmp(section,m_pSection))
	{
	    m_nGlobalState=STAT_APPEND;
	}
    }
}
